In [3]:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from pandas import DataFrame
import re
%pylab inline
In [ ]:
parcel2015 = pd.read_csv('Assessor_Parcels_Data_-_2015.csv',low_memory=False)
Many properties in the City of Los Angeles are listed by alternate city names. For instance, many of the neighborhoods in the Valley (e.g. Encino, Van Nuys) have the neighborhood as its City Name. Thus, we need a more comprehensive strategy to identify parcels in Los Angeles vs other parts of the County.
This script takes a two-part approach. First, we filter based on all Zip Codes that are at least partially in the City of Los Angeles.
In [2]:
parcelLA2015 = parcel2015[(parcel2015.ZIPcode5.isin([91306,
91335,90024,91324,91326,91344,91364,91325,91343,90744,91311,90062,91345,91402,91316,91367,91423,
91356,90292,91042,91604,90077,91342,90049,90210,91331,91304,90290,90069,91040,90293,90067,90059,
91403,90003,90008,90064,91405,91406,90272,90011,90731,90501,91307,90248,90047,90036,90502,90002,
90025,90007,90710,90037,91352,91607,90732,90045,90046,90068,90035,90402,90247,90810,91303,91340,
90043,91436,91602,90048,91411,90044,90230,91504,91401,90018,90063,90056,90001,90032,90057,90023,
91606,90033,90066,90094,91605,90061,90041,90021,90010,90813,90014,90034,90015,90016,90031,90019,
90005,90006,90065,90012,90042,90028,90291,90004,90020,90027,90013,90038,90039,91601,90017,90029,
90026,90731,90058,90071,90073,90089,90095,90211,90212,90232,90245,90262,90265,90275,90280,90301,
90302,90304,90305,90403,90404,90405,90504,90717,90745,90802,91030,91105,91201,91202,91204,91205,
91206,91214,91302,91321,91330,91505,91506,91522,91608,91801,91803]))]
Since many Zip Codes cross City boundaries, we then further refine based on the Tax Rate Area City.
Note: Using additional GeoSpatial tools, we can more precicely locate only parcels in the City of Los Angeles. However, this approach assumes that one has limited access to Geospatial tools,libraries or extensions.
In [32]:
parcelLA2015 = parcelLA2015[parcelLA2015.TaxRateArea_CITY == 'LOS ANGELES'].reset_index(drop=True)
In [8]:
#removes some extraneous columns
parcelLA2015.drop(['ZIPcode','TaxRateArea','AdministrativeRegion','Location 1',
'RealEstateExemption','FixtureValue','FixtureExemption','PersonalPropertyValue',
'PersonalPropertyExemption','Cluster','ParcelBoundaryDescription','rowID'],1,inplace=True)
In [9]:
parcelRES = parcelLA2015[parcelLA2015.GeneralUseType=='Residential'].reset_index(drop=True)
Los Angeles' Rent Stabilization Ordinance only applies to particular residential use types. Even within those types, there are particular exemptions, which are not readily identifiable through the Assessor file alone. Since these exemptions and other special use cases are rare and not possible to identify through the Assessor's file, this script currently foregoes these considerations.
In addition, condos that are not owner occupied are also subject to Rent Stabilization. To approximate non-owner occupied condos, we consider those that have $0 for the Homeowners Exemptions.
In [10]:
RSOtype = ['Five or More Units or Apartments (Any Combination)',
'Double, Duplex, or Two Units', 'Four Units (Any Combination)',
'Three Units (Any Combination)', 'Rooming/Boarding House']
parcelRES['RSO eligible'] = parcelRES['SpecificUseType'].isin(RSOtype)
#function to determine if the parcel fits into "RSO-eligible property."
#As noted above, condos (primarily single family) are re-added based
def RSOclass(df):
if df['RSO eligible'] is True:
return 'RSO eligible'
elif(((df['SpecificUseDetail2']=='Condominium')|
(df['SpecificUseDetail2']=='Condo Conversion')|
(df['SpecificUseDetail2']=='Cooperative'))
&(df['HomeownersExemption']=='$0.00')):
return 'RSO eligible'
else:
return 'Non RSO eligible'
#apply the function to the Residential parcels
parcelRES['RSO eligible'] = parcelRES.apply(RSOclass,axis=1)
In Los Angeles, only units built on October 1978 or earlier are RSO protected. Since the Assessor File does not specify month, we will consider all propertiers with a Year Built of 1978 or earlier. Since this will not exclude properties built in Nov or Dec 1978, we can unfortunately expect some false positives.
Another data hurdle is that not every parcel has a year built indicated. We'll mark these cases as "RSO unknown." Further research is needed to ascertain these buildings' statuses.
In [11]:
#define function for identifying RSO
def RSO(df):
if df['YearBuilt']<=1978 and df['RSO eligible']== 'RSO eligible' and df['YearBuilt']<>0:
return 'Probably RSO'
elif df['YearBuilt']>1978 and df['RSO eligible'] == 'RSO eligible':
return 'Probably Not RSO'
elif df['YearBuilt']==0 and df['RSO eligible'] == 'RSO eligible':
return 'Unknown'
else:
return 'Not RSO Eligible'
parcelRES['RSO Estimate'] = parcelRES.apply(RSO,axis=1)
In [12]:
probRSO = parcelRES[parcelRES['RSO Estimate']=='Probably RSO'].reset_index(drop=True)
In [17]:
probRSO.to_excel('probRSO.xlsx')